package com.such.kit.string;

import java.io.UnsupportedEncodingException;
import com.such.kit.datacast.CastCommons;
import com.such.kit.validate.ValidateCommons;

/**
 * @author SUCH
 * <pre>
 * 字符串通用工具类
 * </pre>
 */
public class StringCommons {

	/** CHARSET_UTF8：字符集 UTF-8 */
	public static final String CHARSET_UTF8 = "UTF-8";
	/** CHARSET_GBK：字符集 GBK */
	public static final String CHARSET_GBK = "GBK";
	/** RETRACT：缩进符（制表符） */
	public static final String RETRACT = "	";
	/** NEW_LINE：换行符（System.getProperty("line.separator")） */
	public static final String NEW_LINE = System.getProperty("line.separator");

	/**
	 * <pre>
	 * 将字符串转换为小写
	 * </pre>
	 * @param str 字符串
	 * @return 换为小写的字符串
	 */
	public static String toLowerCase(String str) {
		if (ValidateCommons.isNotEmpty(str)) {
			str = str.toLowerCase();
		}
		return str;
	}

	/**
	 * <pre>
	 * 将字符串转换为大写
	 * </pre>
	 * @param str 字符串
	 * @return 换为大写的字符串
	 */
	public static String toUpperCase(String str) {
		if (ValidateCommons.isNotEmpty(str)) {
			str = str.toUpperCase();
		}
		return str;
	}

	/**
	 * <pre>
	 * 将数组拼接为字符串
	 * </pre>
	 * @param array 数组
	 * @param perfix 为数组元素添加前缀
	 * @param suffix 为数组元素添加后缀
	 * @param cutStart 对生成的字符串从头部去掉几个字符
	 * @param cutEnd 对生成的字符串从尾部去掉几个字符
	 * @return 拼接字符串
	 */
	public static String merger(Object[] array, String perfix, String suffix, int cutStart, int cutEnd) {
		StringBuffer buf = new StringBuffer();
		if (ValidateCommons.isNotEmpty(array)) {
			for (Object obj : array) {
				buf.append(perfix).append(obj).append(suffix);
			}
		}
		String str = buf.toString();
		int length = str.length();
		if (length > 0) {
			if (cutStart > 0 && length >= cutStart) {
				str = str.substring(cutStart);
				length = str.length();
			}
			if (cutEnd > 0 && length >= cutEnd) {
				str = str.substring(0, length - cutEnd);
			}
		}
		return str;
	}

	/**
	 * <pre>
	 * 将数组拼接为字符串
	 * </pre>
	 * @param array 数组
	 * @param separator 在数组元素后添加分隔符
	 * @param cutLastSeparator 是否去除尾部的分隔符
	 * @return 拼接字符串
	 */
	public static String merger(Object[] array, String separator, boolean cutLastSeparator) {
		int cutEnd = 0;
		if (cutLastSeparator) {
			cutEnd = separator.length();
		}
		return merger(array, "", separator, 0, cutEnd);
	}

	/**
	 * <pre>
	 * 将数组拼接为字符串
	 * </pre>
	 * @param array 数组
	 * @return 拼接字符串
	 */
	public static String merger(Object... array) {
		StringBuffer buf = new StringBuffer();
		if (ValidateCommons.isNotEmpty(array)) {
			for (Object obj : array) {
				if (obj == null) {
					obj = "";
				}
				buf.append(obj);
			}
		}
		return buf.toString();
	}

	/**
	 * <pre>
	 * 空值处理
	 * str 为空返回 emptyReturn，非空返回 notEmptyReturn
	 * </pre>
	 * @param str 字符串
	 * @param emptyReturn 空处理值
	 * @param notEmptyReturn 非空处理值
	 * @return 处理值
	 */
	public static String emptyValue(String str, String emptyReturn, String notEmptyReturn) {
		if (ValidateCommons.isEmpty(str)) {
			return emptyReturn;
		} else {
			return notEmptyReturn;
		}
	}

	/**
	 * <pre>
	 * 空值处理
	 * str 为空返回 emptyReturn，非空返回 str
	 * </pre>
	 * @param str 字符串
	 * @param emptyReturn 空处理值
	 * @return 处理值
	 */
	public static String emptyValue(String str, String emptyReturn) {
		return emptyValue(str, emptyReturn, str);
	}

	/**
	 * <pre>
	 * 重复字符串
	 * </pre>
	 * @param str 字符串
	 * @param perfix 为字符串添加前缀
	 * @param suffix 为字符串添加后缀
	 * @param time 重复次数
	 * @param cutStart 对生成的字符串从头部去掉几个字符
	 * @param cutEnd 对生成的字符串从尾部去掉几个字符
	 * @return 重复字符串
	 */
	public static String repeat(String str, String perfix, String suffix, int time, int cutStart, int cutEnd) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < time; i++) {
			buf.append(perfix).append(str).append(suffix);
		}
		str = buf.toString();
		int length = str.length();
		if (length > 0) {
			if (cutStart > 0 && length >= cutStart) {
				str = str.substring(cutStart);
				length = str.length();
			}
			if (cutEnd > 0 && length >= cutEnd) {
				str = str.substring(0, length - cutEnd);
			}
		}
		return str;
	}

	/**
	 * <pre>
	 * 重复字符串
	 * </pre>
	 * @param str 字符串
	 * @param separator 在字符串后添加分隔符
	 * @param time 重复次数
	 * @param cutLastSeparator 是否去除尾部的分隔符
	 * @return 重复字符串
	 */
	public static String repeat(String str, String separator, int time, boolean cutLastSeparator) {
		int cutEnd = 0;
		if (cutLastSeparator) {
			cutEnd = separator.length();
		}
		return repeat(str, "", separator, time, 0, cutEnd);
	}

	/**
	 * <pre>
	 * 重复字符串
	 * </pre>
	 * @param str 字符串
	 * @param time 重复次数
	 * @return 重复字符串
	 */
	public static String repeat(String str, int time) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < time; i++) {
			buf.append(str);
		}
		return buf.toString();
	}

	/**
	 * <pre>
	 * 计算字符串长度
	 * 
	 * useStrictlyLength 为 true 时会对方块字作多位处理，不同字符集对方块字的精确长度计算规则不同，如 GBK 计为 2、UTF-8 计为 3
	 * </pre>
	 * @param str 字符串
	 * @param charset 字符集
	 * @param useStrictlyLength 是否使用严格计算
	 * @return 字符串长度
	 */
	public static int length(String str, String charset, boolean useStrictlyLength) {
		int length = 0;
		if (ValidateCommons.isNotEmpty(str)) {
			if (useStrictlyLength) {
				byte[] byteArray = CastCommons.stringToBytes(str, charset);
				length = byteArray.length;
			} else {
				length = str.length();
			}
		}
		return length;
	}

	/**
	 * <pre>
	 * [参考 {@link #length(String, String, boolean)}]
	 * 
	 * charset 默认为当前系统字符集
	 * </pre>
	 */
	public static int length(String str, boolean useStrictlyLength) {
		return length(str, null, useStrictlyLength);
	}

	/**
	 * <pre>
	 * 计算字符串长度
	 * </pre>
	 * @param str 字符串
	 * @param unasciiLength 非标准 ASCII 码占用位数
	 * @return 字符串长度
	 */
	public static int length(String str, int unasciiLength) {
		int length = 0;
		for (int i = 0; i < str.length(); i++) {
			int code = Character.codePointAt(str, i);
			// 标准 ascii 取值范围在 0 到 255 之间
			if (code >= 0 && code <= 255) {
				length++;
			} else {
				length += unasciiLength;
			}
		}
		return length;
	}

	/**
	 * <pre>
	 * 截取字符串
	 * 
	 * useStrictlySub 为 true 时会对方块字作多位处理，不同字符集对方块字的精确长度计算规则不同，如 GBK 计为 2、UTF-8 计为 3
	 * </pre>
	 * @param str 字符串
	 * @param start 开始位置
	 * @param end 结束位置
	 * @param charset 字符集
	 * @param useStrictlySub 是否使用严格截取
	 * @return 截取后的字符串
	 */
	public static String substring(String str, int start, int end, String charset, boolean useStrictlySub) {
		if (ValidateCommons.isNotEmpty(str)) {
			if (useStrictlySub) {
				byte[] byteArray = CastCommons.stringToBytes(str, charset);
				int length = byteArray.length;
				if (length > start && length > end) {
					byteArray = copyOfRange(byteArray, start, end);
					if (ValidateCommons.isEmpty(charset)) {
						str = new String(byteArray);
					} else {
						try {
							str = new String(byteArray, charset);
						} catch (UnsupportedEncodingException e) {
							str = new String(byteArray);
						}
					}
					int strLen = str.length();
					// 处理截取乱码
					if ("�".charAt(0) == str.charAt(strLen - 1)) {
						str = str.substring(0, strLen - 1);
					}
				}
			} else {
				int length = str.length();
				if (length > end) {
					str = str.substring(start, end);
				}
			}
		}
		return str;
	}

	/**
	 * <pre>
	 * [参考 {@link #substring(String, int, int, String, boolean)}]
	 * 
	 * charset 默认为当前系统字符集
	 * </pre>
	 */
	public static String substring(String str, int begin, int end, boolean useStrictlySub) {
		return substring(str, begin, end, null, useStrictlySub);
	}

	/**
	 * <pre>
	 * [参考 {@link #substring(String, int, int, String, boolean)}]
	 * 
	 * useStrictlySub 默认为 true
	 * </pre>
	 */
	public static String substring(String str, int begin, int end, String charset) {
		return substring(str, begin, end, charset, true);
	}

	/**
	 * <pre>
	 * [参考 {@link #substring(String, int, int, String, boolean)}]
	 * 
	 * charset 默认为当前系统字符集
	 * useStrictlySub 默认为 true
	 * </pre>
	 */
	public static String substring(String str, int begin, int end) {
		return substring(str, begin, end, null, true);
	}

	/**
	 * <pre>
	 * 截取数组
	 * 
	 * 当 to 小于等于 from 时不作处理
	 * 当数组长度小于等于 from、to 时不作处理
	 * </pre>
	 * @param array 数组
	 * @param from 开始位置
	 * @param to 结束位置
	 * @return 截取后的数组
	 */
	public static byte[] copyOfRange(byte[] array, int from, int to) {
		int copyLen = to - from;
		if (copyLen <= 0) {
			return array;
		}
		int len = array.length;
		if (len <= from || len <= to) {
			return array;
		}
		byte[] copy = new byte[copyLen];
		System.arraycopy(array, from, copy, 0, Math.min(len - from, copyLen));
		return copy;
	}

	/**
	 * <pre>
	 * 格式化字符串长度
	 * 将字符串格式到统一长度，当长度不够时，在字符串后面补空格
	 * 
	 * useStrictlyLength 为 true 时会对方块字作多位处理，不同字符集对方块字的精确长度计算规则不同，如 GBK 计为 2、UTF-8 计为 3
	 * </pre>
	 * @param str 字符串
	 * @param length 统一长度
	 * @param charset 字符集
	 * @param useStrictlyLength 是否使用严格计算
	 * @return 格式化后的字符串
	 */
	public static String formatStringLength(String str, int length, String charset, boolean useStrictlyLength) {
		int checkLength = length(str, charset, useStrictlyLength);
		if (length > checkLength) {
			for (int i = checkLength; i < length; i++) {
				str += ' ';
			}
		}
		return str;
	}

	/**
	 * <pre>
	 * [参考 {@link #formatStringLength(String, int, String, boolean)}]
	 * 
	 * charset 默认为当前系统字符集
	 * </pre>
	 */
	public static String formatStringLength(String str, int length, boolean useStrictlyLength) {
		return formatStringLength(str, length, null, useStrictlyLength);
	}

}
